package pl.donajski.magisterka;

import java.util.List;

import javax.management.RuntimeErrorException;

public class CharyHeuristicGenerator implements IInitialStateGenerator {

	public State getInitialState(List<Task> tasks, List<Node> nodes) {
		this.mState = new State(tasks, nodes);
		
		this.initialize();
		return this.mState;
	}
	
	
	private void initialize() {
		SubstitutionGenerator sg = new SubstitutionGenerator(mState, 1f);
		float avgOFlow = this.calcAvgOFlow();
		for(Task t : mState.getTasks()) {
		
			Node best    = null;
			float bestCost = Float.MAX_VALUE;
			
			for(Node d : t.getDestinations()) {
				if(!t.canAssign(d)) {
					continue;
				}
				
				float unitFlow = (float) d.getCapacityModuleOpex() / d.getCapacityModuleSize();
				float flowC    = (float) unitFlow * t.getOutputTransmissionRate();
				float procC    = (float) d.getProcessingOpex();
				if(flowC + procC < bestCost) {
					best = d;
					bestCost = flowC + procC;
				}
			}
			
			if(best != null) {
				t.setAssignment(best);
				continue;
			}
			
			/*
			 * in case no destination move was possible
			 * 1. try source
			 * 2. get best of nodes left
			 */
			if(t.canAssign(t.getSourceNode())) {
				t.setAssignment(t.getSourceNode());
				continue;
			}
			
			best   = null;
			bestCost = Float.MAX_VALUE;
			
			for(Node n : mState.getNodes()) {
				if(!t.canAssign(n))
					continue;
				
				float procC = (float) n.getProcessingOpex();
				
				if(procC < bestCost) {
					best = n;
					bestCost = procC;
				}
			}
			
			t.setAssignment(best);
		}
		
		this.mState.setFlows();
		this.mState.calculateCost();
		
		if(!this.mState.isValid())
			assert(false);
		
	}


	private float calcAvgOFlow() {
		float c = 0;
		for(Task t : this.mState.getTasks()) {
			c += t.getOutputTransmissionRate();
		}
		
		
		return 0;
	}
	
	private float calcAvgIFlow() {
		float c = 0;
		for(Task t : this.mState.getTasks()) {
			c += t.getInputTransmissionRate();
		}
		
		
		return 0;
	}


	private State mState;

}
